home *** CD-ROM | disk | FTP | other *** search
/ Creative Computers / Creative Computers CD-ROM, Volume 1 (Legendary Design Technologies, Inc.)(1994).iso / shareware / telecom / term_4.1 / extras / hydracom / hydracom-source.lha / hydra.c < prev    next >
C/C++ Source or Header  |  1994-07-02  |  89KB  |  2,015 lines

  1. /*=============================================================================
  2.  
  3.                               HydraCom Version 1.00
  4.  
  5.                          A sample implementation of the
  6.                    HYDRA Bi-Directional File Transfer Protocol
  7.  
  8.                              HydraCom was written by
  9.                    Arjen G. Lentz, LENTZ SOFTWARE-DEVELOPMENT
  10.                   COPYRIGHT (C) 1991-1993; ALL RIGHTS RESERVED
  11.  
  12.                        The HYDRA protocol was designed by
  13.                  Arjen G. Lentz, LENTZ SOFTWARE-DEVELOPMENT and
  14.                              Joaquim H. Homrighausen
  15.                   COPYRIGHT (C) 1991-1993; ALL RIGHTS RESERVED
  16.  
  17.  
  18.   Revision history:
  19.   06 Sep 1991 - (AGL) First tryout
  20.   .. ... .... - Internal development
  21.   11 Jan 1993 - HydraCom version 1.00, Hydra revision 001 (01 Dec 1992)
  22.  
  23.  
  24.   For complete details of the Hydra and HydraCom licensing restrictions,
  25.   please refer to the license agreements which are published in their entirety
  26.   in HYDRACOM.C and LICENSE.DOC, and also contained in the documentation file
  27.   HYDRACOM.DOC
  28.  
  29.   Use of this file is subject to the restrictions contained in the Hydra and
  30.   HydraCom licensing agreements. If you do not find the text of this agreement
  31.   in any of the aforementioned files, or if you do not have these files, you
  32.   should immediately contact LENTZ SOFTWARE-DEVELOPMENT and/or Joaquim
  33.   Homrighausen at one of the addresses listed below. In no event should you
  34.   proceed to use this file without having accepted the terms of the Hydra and
  35.   HydraCom licensing agreements, or such other agreement as you are able to
  36.   reach with LENTZ SOFTWARE-DEVELOMENT and Joaquim Homrighausen.
  37.  
  38.  
  39.   Hydra protocol design and HydraCom driver:         Hydra protocol design:
  40.   Arjen G. Lentz                                     Joaquim H. Homrighausen
  41.   LENTZ SOFTWARE-DEVELOPMENT                         389, route d'Arlon
  42.   Langegracht 7B                                     L-8011 Strassen
  43.   3811 BT  Amersfoort                                Luxembourg
  44.   The Netherlands
  45.   FidoNet 2:283/512, AINEX-BBS +31-33-633916         FidoNet 2:270/17
  46.   arjen_lentz@f512.n283.z2.fidonet.org               joho@ae.lu
  47.  
  48.   Please feel free to contact us at any time to share your comments about our
  49.   software and/or licensing policies.
  50.  
  51. =============================================================================*/
  52.  
  53. #include "hydracom.h"                             /* need 2types.h & hydra.h */
  54.  
  55. #ifdef AMIGA
  56. #include <dos/dos.h>
  57. #include <clib/dos_protos.h>
  58. #endif    /* AMIGA */
  59.  
  60. #define H_DEBUG 1
  61.  
  62. #ifdef AMIGA        /* OLSEN */
  63. #define FNAMELEN 31
  64. #else
  65. #define FNAMELEN 13
  66. #endif    /* AMIGA */
  67.  
  68. /* HYDRA Some stuff to aid readability of the source and prevent typos ----- */
  69. #define h_updcrc16(crc,c)  (crc16tab[(       crc ^ (c)) & 0xff] ^ ((crc >> 8) & 0x00ff))
  70. #define h_updcrc32(crc,c)  (crc32tab[((byte) crc ^ (c)) & 0xff] ^ ((crc >> 8) & 0x00ffffffL))
  71. #define h_crc16poly        (0x8408)
  72. #define h_crc32poly        (0xedb88320L)
  73. #define h_crc16test(crc)   (((crc) == 0xf0b8     ) ? 1 : 0)
  74. #define h_crc32test(crc)   (((crc) == 0xdebb20e3L) ? 1 : 0)
  75. #define h_uuenc(c)         (((c) & 0x3f) + '!')
  76. #define h_uudec(c)         (((c) - '!') & 0x3f)
  77. #define h_long1(buf)       (*((long *) (buf)))
  78. #define h_long2(buf)       (*((long *) ((buf) + ((int) sizeof (long)))))
  79. #define h_long3(buf)       (*((long *) ((buf) + (2 * ((int) sizeof (long))))))
  80. typedef long               h_timer;
  81. #define h_timer_set(t)     (time(NULL) + (t))
  82. #define h_timer_running(t) (t != 0L)
  83. #define h_timer_expired(t) (time(NULL) > (t))
  84. #define h_timer_reset()    (0L)
  85.  
  86.  
  87. /* HYDRA's memory ---------------------------------------------------------- */
  88. static  boolean originator;                     /* are we the orig side?     */
  89. static  int     batchesdone;                    /* No. HYDRA batches done    */
  90. static  boolean hdxlink;                        /* hdx link & not orig side  */
  91. static  dword   options;                        /* INIT options hydra_init() */
  92. static  word    timeout;                        /* general timeout in secs   */
  93. static  char    abortstr[] = { 24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 };
  94. static  char   *hdxmsg     = "Fallback to one-way xfer";
  95. static  char   *pktprefix  = "";
  96. static  char   *autostr    = "hydra\r";
  97. static  word   *crc16tab;                       /* CRC-16 table              */
  98. static  dword  *crc32tab;                       /* CRC-32 table              */
  99.  
  100. static  byte   *txbuf,         *rxbuf;          /* packet buffers            */
  101. static  dword   txoptions,      rxoptions;      /* HYDRA options (INIT seq)  */
  102. static  char    txpktprefix[H_PKTPREFIX + 1];   /* pkt prefix str they want  */
  103. static  long    txwindow,       rxwindow;       /* window size (0=streaming) */
  104. static  h_timer                 braindead;      /* braindead timer           */
  105. static  byte   *txbufin;                        /* read data from disk here  */
  106. static  byte    txlastc;                        /* last byte put in txbuf    */
  107. static  byte                    rxdle;          /* count of received H_DLEs  */
  108. static  byte                    rxpktformat;    /* format of pkt receiving   */
  109. static  byte                   *rxbufptr;       /* current position in rxbuf */
  110. static  byte                   *rxbufmax;       /* highwatermark of rxbuf    */
  111. static  char    txfname[FNAMELEN],    rxfname[FNAMELEN];    /* fname of current files   */ /* OLSEN */
  112. static  char                   *rxpathname;     /* pointer to rx pathname    */
  113. static  long    txftime,        rxftime;        /* file timestamp (UNIX)     */
  114. static  long    txfsize,        rxfsize;        /* file length               */
  115. static  int     txfd,           rxfd;           /* file handles              */
  116. static  word                    rxpktlen;       /* length of last packet     */
  117. static  word                    rxblklen;       /* len of last good data blk */
  118. static  byte    txstate,        rxstate;        /* xmit/recv states          */
  119. static  long    txpos,          rxpos;          /* current position in files */
  120. static  word    txblklen;                       /* length of last block sent */
  121. static  word    txmaxblklen;                    /* max block length allowed  */
  122. static  long    txlastack;                      /* last dataack received     */
  123. static  long    txstart,        rxstart;        /* time we started this file */
  124. static  long    txoffset,       rxoffset;       /* offset in file we begun   */
  125. static  h_timer txtimer,        rxtimer;        /* retry timers              */
  126. static  word    txretries,      rxretries;      /* retry counters            */
  127. static  long                    rxlastsync;     /* filepos last sync retry   */
  128. static  long    txsyncid,       rxsyncid;       /* id of last resync         */
  129. static  word    txgoodneeded;                   /* to send before larger blk */
  130. static  word    txgoodbytes;                    /* no. sent at this blk size */
  131.  
  132. struct _h_flags {
  133.         char  *str;
  134.         dword  val;
  135. };
  136.  
  137. static struct _h_flags h_flags[] = {
  138.         { "XON", HOPT_XONXOFF },
  139.         { "TLN", HOPT_TELENET },
  140.         { "CTL", HOPT_CTLCHRS },
  141.         { "HIC", HOPT_HIGHCTL },
  142.         { "HI8", HOPT_HIGHBIT },
  143.         { "BRK", HOPT_CANBRK  },
  144.         { "ASC", HOPT_CANASC  },
  145.         { "UUE", HOPT_CANUUE  },
  146.         { "C32", HOPT_CRC32   },
  147.         { "DEV", HOPT_DEVICE  },
  148.         { "FPT", HOPT_FPT     },
  149.         { NULL , 0x0L         }
  150. };
  151.  
  152.  
  153. /*---------------------------------------------------------------------------*/
  154. static void hydra_msgdev (byte *data, word len)
  155. {       /* text is already NUL terminated by calling func hydra_devrecv() */
  156.         len = len;
  157.         message(3,"*HMSGDEV: %s",data);
  158. }/*hydra_msgdev()*/
  159.  
  160.  
  161. /*---------------------------------------------------------------------------*/
  162. static  word    devtxstate;                     /* dev xmit state            */
  163. static  h_timer devtxtimer;                     /* dev xmit retry timer      */
  164. static  word    devtxretries;                   /* dev xmit retry counter    */
  165. static  long    devtxid,        devrxid;        /* id of last devdata pkt    */
  166. static  char    devtxdev[H_FLAGLEN + 1];        /* xmit device ident flag    */
  167. static  byte   *devtxbuf;                       /* ptr to usersupplied dbuf  */
  168. static  word    devtxlen;                       /* len of data in xmit buf   */
  169.  
  170. struct _h_dev {
  171.         char  *dev;
  172.         void (*func) (byte *data, word len);
  173. };
  174.  
  175. static  struct _h_dev h_dev[] = {
  176.         { "MSG", hydra_msgdev },                /* internal protocol msg     */
  177.         { "CON", NULL         },                /* text to console (chat)    */
  178.         { "PRN", NULL         },                /* data to printer           */
  179.         { "ERR", NULL         },                /* text to error output      */
  180.         { NULL , NULL         }
  181. };
  182.  
  183.  
  184. /*---------------------------------------------------------------------------*/
  185. boolean hydra_devfree (void)
  186. {
  187.         if (devtxstate || !(txoptions & HOPT_DEVICE) || txstate >= HTX_END)
  188.            return (false);                      /* busy or not allowed       */
  189.         else
  190.            return (true);                       /* allowed to send a new pkt */
  191. }/*hydra_devfree()*/
  192.  
  193.  
  194. /*---------------------------------------------------------------------------*/
  195. boolean hydra_devsend (char *dev, byte *data, word len)
  196. {
  197.         if (!dev || !data || !len || !hydra_devfree())
  198.            return (false);
  199.  
  200.         strncpy(devtxdev,dev,H_FLAGLEN);
  201.         devtxdev[H_FLAGLEN] = '\0';
  202. #ifndef AMIGA
  203.         strupr(devtxdev);
  204. #endif    /* AMIGA */
  205.         devtxbuf = data;
  206.         devtxlen = (len > H_MAXBLKLEN) ? H_MAXBLKLEN : len;
  207.  
  208.         devtxid++;
  209.         devtxtimer   = h_timer_reset();
  210.         devtxretries = 0;
  211.         devtxstate   = HTD_DATA;
  212.  
  213.         /* special for chat, only prolong life if our side keeps typing! */
  214.         if (chattimer > 0L && !strcmp(devtxdev,"CON") && txstate == HTX_REND)
  215.            braindead = h_timer_set(H_BRAINDEAD);
  216.  
  217.         return (true);
  218. }/*hydra_devsend()*/
  219.  
  220.  
  221. /*---------------------------------------------------------------------------*/
  222. boolean hydra_devfunc (char *dev, void (*func) (byte *data, word len))
  223. {
  224.         register int i;
  225.  
  226.         for (i = 0; h_dev[i].dev; i++) {
  227.             if (!strnicmp(dev,h_dev[i].dev,H_FLAGLEN)) {
  228.                h_dev[i].func = func;
  229.                return (true);
  230.             }
  231.         }
  232.  
  233.         return (false);
  234. }/*hydra_devfunc()*/
  235.  
  236.  
  237. /*---------------------------------------------------------------------------*/
  238. static void hydra_devrecv (void)
  239. {
  240.         register char *p = (char *) rxbuf;
  241.         register int   i;
  242.         word len = rxpktlen;
  243.  
  244.         p += (int) sizeof (long);                       /* skip the id long  */
  245.         len -= (int) sizeof (long);
  246.         for (i = 0; h_dev[i].dev; i++) {                /* walk through devs */
  247.             if (!strncmp(p,h_dev[i].dev,H_FLAGLEN)) {
  248.                if (h_dev[i].func) {
  249.                   len -= ((int) strlen(p)) + 1;         /* sub devstr len    */
  250.                   p += ((int) strlen(p)) + 1;           /* skip devtag       */
  251.                   p[len] = '\0';                        /* NUL terminate     */
  252.                   (*h_dev[i].func)((byte *) p,len);     /* call output func  */
  253.                }
  254.                break;
  255.             }
  256.         }
  257. }/*hydra_devrecv()*/
  258.  
  259.  
  260. /*---------------------------------------------------------------------------*/
  261. static void put_flags (char *buf, struct _h_flags flags[], long val)
  262. {
  263.         register char *p;
  264.         register int   i;
  265.  
  266.         p = buf;
  267.         for (i = 0; flags[i].val; i++) {
  268.             if (val & flags[i].val) {
  269.                if (p > buf) *p++ = ',';
  270.                strcpy(p,flags[i].str);
  271.                p += H_FLAGLEN;
  272.             }
  273.         }
  274.         *p = '\0';
  275. }/*put_flags()*/
  276.  
  277.  
  278. /*---------------------------------------------------------------------------*/
  279. static dword get_flags (char *buf, struct _h_flags flags[])
  280. {
  281.         register dword  val;
  282.         register char  *p;
  283.         register int    i;
  284.  
  285.         val = 0x0L;
  286.         for (p = strtok(buf,","); p; p = strtok(NULL,",")) {
  287.             for (i = 0; flags[i].val; i++) {
  288.                 if (!strcmp(p,flags[i].str)) {
  289.                    val |= flags[i].val;
  290.                    break;
  291.                 }
  292.             }
  293.         }
  294.  
  295.         return (val);
  296. }/*get_flags()*/
  297.  
  298.  
  299. /*---------------------------------------------------------------------------*/
  300. static word crc16block (register byte *buf, register word len)
  301. {
  302.         register word crc;
  303.  
  304.         for (crc = 0xffff; len > 0; len--)
  305.             crc = h_updcrc16(crc,*buf++);
  306.         return (crc);
  307. }/*crc16block()*/
  308.  
  309.  
  310. /*---------------------------------------------------------------------------*/
  311. static dword crc32block (register byte *buf, register word len)
  312. {
  313.         register dword crc;
  314.  
  315.         for (crc = 0xffffffffL; len > 0; len--)
  316.             crc = h_updcrc32(crc,*buf++);
  317.         return (crc);
  318. }/*crc32block()*/
  319.  
  320.  
  321. /*---------------------------------------------------------------------------*/
  322. static byte *put_binbyte (register byte *p, register byte c)
  323. {
  324.         register byte n;
  325.  
  326.         n = c;
  327.         if (txoptions & HOPT_HIGHCTL)
  328.            n &= 0x7f;
  329.  
  330.         if (n == H_DLE ||
  331.             ((txoptions & HOPT_XONXOFF) && (n == XON || n == XOFF)) ||
  332.             ((txoptions & HOPT_TELENET) && n == '\r' && txlastc == '@') ||
  333.             ((txoptions & HOPT_CTLCHRS) && (n < 32 || n == 127))) {
  334.            *p++ = H_DLE;
  335.            c ^= 0x40;
  336.         }
  337.  
  338.         *p++ = c;
  339.         txlastc = n;
  340.  
  341.         return (p);
  342. }/*put_binbyte()*/
  343.  
  344.  
  345. /*---------------------------------------------------------------------------*/
  346. static void txpkt (register word len, int type)
  347. {
  348.         register byte *in, *out;
  349.         register word  c, n;
  350.         boolean crc32 = false;
  351.         byte    format;
  352.         static char hexdigit[] = "0123456789abcdef";
  353.  
  354.         txbufin[len++] = type;
  355.  
  356.         switch (type) {
  357.                case HPKT_START:
  358.                case HPKT_INIT:
  359.                case HPKT_INITACK:
  360.                case HPKT_END:
  361.                case HPKT_IDLE:
  362.                     format = HCHR_HEXPKT;
  363.                     break;
  364.  
  365.                default:
  366.                     /* COULD do smart format selection depending on data and options! */
  367.                     if (txoptions & HOPT_HIGHBIT) {
  368.                        if ((txoptions & HOPT_CTLCHRS) && (txoptions & HOPT_CANUUE))
  369.                           format = HCHR_UUEPKT;
  370.                        else if (txoptions & HOPT_CANASC)
  371.                           format = HCHR_ASCPKT;
  372.                        else
  373.                           format = HCHR_HEXPKT;
  374.                     }
  375.                     else
  376.                        format = HCHR_BINPKT;
  377.                     break;
  378.         }
  379.  
  380.         if (format != HCHR_HEXPKT && (txoptions & HOPT_CRC32))
  381.            crc32 = true;
  382.  
  383. #if H_DEBUG
  384. if (loglevel==0) {
  385.    char *s1, *s2, *s3, *s4;
  386.  
  387.    message(0," -> PKT (format='%c'  type='%c'  crc=%d  len=%d)",
  388.              format, type, crc32 ? 32 : 16, len - 1);
  389.  
  390.    switch (type) {
  391.           case HPKT_START:    message(0,"    <autostr>START");
  392.                               break;
  393.           case HPKT_INIT:     s1 = ((char *) txbufin) + ((int) strlen((char *) txbufin)) + 1;
  394.                               s2 = s1 + ((int) strlen(s1)) + 1;
  395.                               s3 = s2 + ((int) strlen(s2)) + 1;
  396.                               s4 = s3 + ((int) strlen(s3)) + 1;
  397.                               message(0,"    INIT (appinfo='%s'  can='%s'  want='%s'  options='%s'  pktprefix='%s')",
  398.                                       (char *) txbufin, s1, s2, s3, s4);
  399.                               break;
  400.           case HPKT_INITACK:  message(0,"    INITACK");
  401.                               break;
  402.           case HPKT_FINFO:    message(0,"    FINFO (%s)",txbufin);
  403.                               break;
  404.           case HPKT_FINFOACK: if (rxfd >= 0) {
  405.                                  if (rxpos > 0L) s1 = "RES";
  406.                                  else            s1 = "BOF";
  407.                               }
  408.                               else if (rxpos == -1L) s1 = "HAVE";
  409.                               else if (rxpos == -2L) s1 = "SKIP";
  410.                               else                   s1 = "EOB";
  411.                               message(0,"    FINFOACK (pos=%ld %s  rxstate=%d  rxfd=%d)",
  412.                                       rxpos,s1,rxstate,rxfd);
  413.                               break;
  414.           case HPKT_DATA:     message(0,"    DATA (ofs=%ld  len=%d)",
  415.                                       intell(h_long1(txbufin)), len - 5);
  416.                               break;
  417.           case HPKT_DATAACK:  message(0,"    DATAACK (ofs=%ld)",
  418.                                       intell(h_long1(txbufin)));
  419.                               break;
  420.           case HPKT_RPOS:     message(0,"    RPOS (pos=%ld%s  blklen=%ld  syncid=%ld)",
  421.                                       rxpos, rxpos < 0L ? " SKIP" : "",
  422.                                       intell(h_long2(txbufin)), rxsyncid);
  423.                               break;
  424.           case HPKT_EOF:      message(0,"    EOF (ofs=%ld%s)",
  425.                                       txpos, txpos < 0L ? " SKIP" : "");
  426.                               break;
  427.           case HPKT_EOFACK:   message(0,"    EOFACK");
  428.                               break;
  429.           case HPKT_IDLE:     message(0,"    IDLE");
  430.                               break;
  431.           case HPKT_END:      message(0,"    END");
  432.                               break;
  433.           case HPKT_DEVDATA:  message(0,"    DEVDATA (id=%ld  dev='%s'  len=%u)",
  434.                                       devtxid, devtxdev, devtxlen);
  435.                               break;
  436.           case HPKT_DEVDACK:  message(0,"    DEVDACK (id=%ld)",
  437.                                       intell(h_long1(rxbuf)));
  438.                               break;
  439.           default:            /* This couldn't possibly happen! ;-) */
  440.                               break;
  441.    }
  442. }
  443. #endif
  444.  
  445.         if (crc32) {
  446.            dword crc = ~crc32block(txbufin,len);
  447.  
  448.            txbufin[len++] = crc;
  449.            txbufin[len++] = crc >> 8;
  450.            txbufin[len++] = crc >> 16;
  451.            txbufin[len++] = crc >> 24;
  452.         }
  453.         else {
  454.            word crc = ~crc16block(txbufin,len);
  455.  
  456.            txbufin[len++] = crc;
  457.            txbufin[len++] = crc >> 8;
  458.         }
  459.  
  460.         in = txbufin;
  461.         out = txbuf;
  462.         txlastc = 0;
  463.         *out++ = H_DLE;
  464.         *out++ = format;
  465.  
  466.         switch (format) {
  467.                case HCHR_HEXPKT:
  468.                     for (; len > 0; len--, in++) {
  469.                         if (*in & 0x80) {
  470.                            *out++ = '\\';
  471.                            *out++ = hexdigit[((*in) >> 4) & 0x0f];
  472.                            *out++ = hexdigit[(*in) & 0x0f];
  473.                         }
  474.                         else if (*in < 32 || *in == 127) {
  475.                            *out++ = H_DLE;
  476.                            *out++ = (*in) ^ 0x40;
  477.                         }
  478.                         else if (*in == '\\') {
  479.                            *out++ = '\\';
  480.                            *out++ = '\\';
  481.                         }
  482.                         else
  483.                            *out++ = *in;
  484.                     }
  485.                     break;
  486.  
  487.                case HCHR_BINPKT:
  488.                     for (; len > 0; len--)
  489.                         out = put_binbyte(out,*in++);
  490.                     break;
  491.  
  492.                case HCHR_ASCPKT:
  493.                     for (n = c = 0; len > 0; len--) {
  494.                         c |= ((*in++) << n);
  495.                         out = put_binbyte(out,c & 0x7f);
  496.                         c >>= 7;
  497.                         if (++n >= 7) {
  498.                            out = put_binbyte(out,c & 0x7f);
  499.                            n = c = 0;
  500.                         }
  501.                     }
  502.                     if (n > 0)
  503.                        out = put_binbyte(out,c & 0x7f);
  504.                     break;
  505.  
  506.                case HCHR_UUEPKT:
  507.                     for ( ; len >= 3; in += 3, len -= 3) {
  508.                         *out++ = h_uuenc(in[0] >> 2);
  509.                         *out++ = h_uuenc(((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f));
  510.                         *out++ = h_uuenc(((in[1] << 2) & 0x3c) | ((in[2] >> 6) & 0x03));
  511.                         *out++ = h_uuenc(in[2] & 0x3f);
  512.                     }
  513.                     if (len > 0) {
  514.                        *out++ = h_uuenc(in[0] >> 2);
  515.                        *out++ = h_uuenc(((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f));
  516.                        if (len == 2)
  517.                           *out++ = h_uuenc((in[1] << 2) & 0x3c);
  518.                     }
  519.                     break;
  520.         }
  521.  
  522.         *out++ = H_DLE;
  523.         *out++ = HCHR_PKTEND;
  524.  
  525.         if (type != HPKT_DATA && format != HCHR_BINPKT) {
  526.            *out++ = '\r';
  527.            *out++ = '\n';
  528.         }
  529.  
  530.         for (in = (byte *) txpktprefix; *in; in++) {
  531.             switch (*in) {
  532.                    case 221: /* transmit break signal for one second */
  533.                              break;
  534.                    case 222: { h_timer t = h_timer_set(2);
  535.                                while (!h_timer_expired(t))
  536.                                      sys_idle();
  537.                              }
  538.                              break;
  539.                    case 223: com_putbyte(0);
  540.                              break;
  541.                    default:  com_putbyte(*in);
  542.                              break;
  543.             }
  544.         }
  545.  
  546.         com_putblock(txbuf,(word) (out - txbuf));
  547. }/*txpkt()*/
  548.  
  549.  
  550. /*---------------------------------------------------------------------------*/
  551. static int rxpkt (void)
  552. {
  553.         register byte *p, *q;
  554.         register int   c, n, i;
  555.  
  556.         if (keyabort())
  557.            return (H_SYSABORT);
  558.         if (!carrier())
  559.            return (H_CARRIER);
  560.  
  561.         p = rxbufptr;
  562.  
  563.         while ((c = com_getbyte()) >= 0) {
  564.               if (rxoptions & HOPT_HIGHBIT)
  565.                  c &= 0x7f;
  566.  
  567.               n = c;
  568.               if (rxoptions & HOPT_HIGHCTL)
  569.                  n &= 0x7f;
  570.               if (n != H_DLE &&
  571.                   (((rxoptions & HOPT_XONXOFF) && (n == XON || n == XOFF)) ||
  572.                    ((rxoptions & HOPT_CTLCHRS) && (n < 32 || n == 127))))
  573.                  continue;
  574.  
  575.               if (rxdle || c == H_DLE) {
  576.                  switch (c) {
  577.                         case H_DLE:
  578.                              if (++rxdle >= 5)
  579.                                 return (H_CANCEL);
  580.                              break;
  581.  
  582.                         case HCHR_PKTEND:
  583.                              rxbufptr = p;
  584.  
  585.                              switch (rxpktformat) {
  586.                                     case HCHR_BINPKT:
  587.                                          q = rxbufptr;
  588.                                          break;
  589.  
  590.                                     case HCHR_HEXPKT:
  591.                                          for (p = q = rxbuf; p < rxbufptr; p++) {
  592.                                              if (*p == '\\' && *++p != '\\') {
  593.                                                 i = *p;
  594.                                                 n = *++p;
  595.                                                 if ((i -= '0') > 9) i -= ('a' - ':');
  596.                                                 if ((n -= '0') > 9) n -= ('a' - ':');
  597.                                                 if ((i & ~0x0f) || (n & ~0x0f)) {
  598.                                                    i = H_NOPKT;
  599.                                                    break;
  600.                                                 }
  601.                                                 *q++ = (i << 4) | n;
  602.                                              }
  603.                                              else
  604.                                                 *q++ = *p;
  605.                                          }
  606.                                          if (p > rxbufptr)
  607.                                             c = H_NOPKT;
  608.                                          break;
  609.  
  610.                                     case HCHR_ASCPKT:
  611.                                          n = i = 0;
  612.                                          for (p = q = rxbuf; p < rxbufptr; p++) {
  613.                                              i |= ((*p & 0x7f) << n);
  614.                                              if ((n += 7) >= 8) {
  615.                                                 *q++ = (byte) (i & 0xff);
  616.                                                 i >>= 8;
  617.                                                 n -= 8;
  618.                                              }
  619.                                          }
  620.                                          break;
  621.  
  622.                                     case HCHR_UUEPKT:
  623.                                          n = (int) (rxbufptr - rxbuf);
  624.                                          for (p = q = rxbuf; n >= 4; n -= 4, p += 4) {
  625.                                              if (p[0] <= ' ' || p[0] >= 'a' ||
  626.                                                  p[1] <= ' ' || p[1] >= 'a' ||
  627.                                                  p[2] <= ' ' || p[2] >= 'a') {
  628.                                                 c = H_NOPKT;
  629.                                                 break;
  630.                                              }
  631.                                              *q++ = (byte) ((h_uudec(p[0]) << 2) | (h_uudec(p[1]) >> 4));
  632.                                              *q++ = (byte) ((h_uudec(p[1]) << 4) | (h_uudec(p[2]) >> 2));
  633.                                              *q++ = (byte) ((h_uudec(p[2]) << 6) | h_uudec(p[3]));
  634.                                          }
  635.                                          if (n >= 2) {
  636.                                             if (p[0] <= ' ' || p[0] >= 'a') {
  637.                                                c = H_NOPKT;
  638.                                                break;
  639.                                             }
  640.                                             *q++ = (byte) ((h_uudec(p[0]) << 2) | (h_uudec(p[1]) >> 4));
  641.                                             if (n == 3) {
  642.                                                if (p[0] <= ' ' || p[0] >= 'a') {
  643.                                                   c = H_NOPKT;
  644.                                                   break;
  645.                                                }
  646.                                                *q++ = (byte) ((h_uudec(p[1]) << 4) | (h_uudec(p[2]) >> 2));
  647.                                             }
  648.                                          }
  649.                                          break;
  650.  
  651.                                     default:   /* This'd mean internal fluke */
  652. #if H_DEBUG
  653. if (loglevel==0) {
  654.    message(0," <- <PKTEND> (pktformat='%c' dec=%d hex=%02x) ??",
  655.              rxpktformat, rxpktformat, rxpktformat);
  656. }
  657. #endif
  658.                                          c = H_NOPKT;
  659.                                          break;
  660.                              }
  661.  
  662.                              rxbufptr = NULL;
  663.  
  664.                              if (c == H_NOPKT)
  665.                                 break;
  666.  
  667.                              rxpktlen = (word) (q - rxbuf);
  668.                              if (rxpktformat != HCHR_HEXPKT && (rxoptions & HOPT_CRC32)) {
  669.                                 if (rxpktlen < 5) {
  670.                                    c = H_NOPKT;
  671.                                    break;
  672.                                 }
  673.                                 n = h_crc32test(crc32block(rxbuf,rxpktlen));
  674.                                 rxpktlen -= (int) sizeof (long);  /* remove CRC-32 */
  675.                              }
  676.                              else {
  677.                                 if (rxpktlen < 3) {
  678.                                    c = H_NOPKT;
  679.                                    break;
  680.                                 }
  681.                                 n = h_crc16test(crc16block(rxbuf,rxpktlen));
  682.                                 rxpktlen -= (int) sizeof (word);  /* remove CRC-16 */
  683.                              }
  684.  
  685.                              rxpktlen--;                     /* remove type  */
  686.  
  687.                              if (n) {
  688. #if H_DEBUG
  689. if (loglevel==0) {
  690.    char *s1, *s2, *s3, *s4;
  691.  
  692.    message(0," <- PKT (format='%c'  type='%c'  len=%d)",
  693.            rxpktformat, (int) rxbuf[rxpktlen], rxpktlen);
  694.  
  695.    switch (rxbuf[rxpktlen]) {
  696.           case HPKT_START:    message(0,"    START");
  697.                               break;
  698.           case HPKT_INIT:     s1 = ((char *) rxbuf) + ((int) strlen((char *) rxbuf)) + 1;
  699.                               s2 = s1 + ((int) strlen(s1)) + 1;
  700.                               s3 = s2 + ((int) strlen(s2)) + 1;
  701.                               s4 = s3 + ((int) strlen(s3)) + 1;
  702.                               message(0,"    INIT (appinfo='%s'  can='%s'  want='%s'  options='%s'  pktprefix='%s')",
  703.                                       (char *) rxbuf, s1, s2, s3, s4);
  704.                               break;
  705.           case HPKT_INITACK:  message(0,"    INITACK");
  706.                               break;
  707.           case HPKT_FINFO:    message(0,"    FINFO ('%s'  rxstate=%d)",rxbuf,rxstate);
  708.                               break;
  709.           case HPKT_FINFOACK: message(0,"    FINFOACK (pos=%ld  txstate=%d  txfd=%d)",
  710.                                       intell(h_long1(rxbuf)), txstate, txfd);
  711.                               break;
  712.           case HPKT_DATA:     message(0,"    DATA (rxstate=%d  pos=%ld  len=%u)",
  713.                                       rxstate, intell(h_long1(rxbuf)),
  714.                                       (word) (rxpktlen - ((int) sizeof (long))));
  715.                               break;
  716.           case HPKT_DATAACK:  message(0,"    DATAACK (rxstate=%d  pos=%ld)",
  717.                                       rxstate, intell(h_long1(rxbuf)));
  718.                               break;
  719.           case HPKT_RPOS:     message(0,"    RPOS (pos=%ld%s  blklen=%u->%ld  syncid=%ld%s  txstate=%d  txfd=%d)",
  720.                                       intell(h_long1(rxbuf)),
  721.                                       intell(h_long1(rxbuf)) < 0L ? " SKIP" : "",
  722.                                       txblklen, intell(h_long2(rxbuf)),
  723.                                       intell(h_long3(rxbuf)),
  724.                                       intell(h_long3(rxbuf)) == rxsyncid ? " DUP" : "",
  725.                                       txstate, txfd);
  726.                               break;
  727.           case HPKT_EOF:      message(0,"    EOF (rxstate=%d  pos=%ld%s)",
  728.                                       rxstate, intell(h_long1(rxbuf)),
  729.                                       intell(h_long1(rxbuf)) < 0L ? " SKIP" : "");
  730.                               break;
  731.           case HPKT_EOFACK:   message(0,"    EOFACK (txstate=%d)", txstate);
  732.                               break;
  733.           case HPKT_IDLE:     message(0,"    IDLE");
  734.                               break;
  735.           case HPKT_END:      message(0,"    END");
  736.                               break;
  737.           case HPKT_DEVDATA:  s1 = ((char *) rxbuf) + ((int) sizeof (long));
  738.                               message(0,"    DEVDATA (id=%ld  dev=%s  len=%u",
  739.                                       intell(h_long1(rxbuf)), s1,
  740.                                       rxpktlen - (((int) sizeof (long)) + ((int) strlen(s1)) + 1));
  741.                               break;
  742.           case HPKT_DEVDACK:  message(0,"    DEVDACK (devtxstate=%d  id=%ld)",
  743.                                       devtxstate, intell(h_long1(rxbuf)));
  744.                               break;
  745.           default:            message(0,"    Unkown pkttype %d (txstate=%d  rxstate=%d)",
  746.                                       (int) rxbuf[rxpktlen], txstate, rxstate);
  747.                               break;
  748.    }
  749. }
  750. #endif
  751.                                 return ((int) rxbuf[rxpktlen]);
  752.                              }/*goodpkt*/
  753.  
  754. #if H_DEBUG
  755. if (loglevel==0)
  756.    message(0," Bad CRC (format='%c'  type='%c'  len=%d)",
  757.              rxpktformat, (int) rxbuf[rxpktlen], rxpktlen);
  758. #endif
  759.                              break;
  760.  
  761.                         case HCHR_BINPKT:
  762.                         case HCHR_HEXPKT:
  763.                         case HCHR_ASCPKT:
  764.                         case HCHR_UUEPKT:
  765. #if H_DEBUG
  766. if (loglevel==0)
  767.    message(0," <- <PKTSTART> (pktformat='%c')",c);
  768. #endif
  769.                              rxpktformat = c;
  770.                              p = rxbufptr = rxbuf;
  771.                              rxdle = 0;
  772.                              break;
  773.  
  774.                         default:
  775.                              if (p) {
  776.                                 if (p < rxbufmax)
  777.                                    *p++ = (byte) (c ^ 0x40);
  778.                                 else {
  779. #if H_DEBUG
  780. if (loglevel==0)
  781.    message(0," <- Pkt too long - discarded");
  782. #endif
  783.                                    p = NULL;
  784.                                 }
  785.                              }
  786.                              rxdle = 0;
  787.                              break;
  788.                  }
  789.               }
  790.               else if (p) {
  791.                  if (p < rxbufmax)
  792.                     *p++ = (byte) c;
  793.                  else {
  794. #if H_DEBUG
  795. if (loglevel==0)
  796.    message(0," <- Pkt too long - discarded");
  797. #endif
  798.                     p = NULL;
  799.                  }
  800.               }
  801.         }
  802.  
  803.         rxbufptr = p;
  804.  
  805.         if (h_timer_running(braindead) && h_timer_expired(braindead)) {
  806. #if H_DEBUG
  807. if (loglevel==0)
  808.    message(0," <- BrainDead (timer=%08lx  time=%08lx)",
  809.            braindead,time(NULL));
  810. #endif
  811.            return (H_BRAINTIME);
  812.         }
  813.         if (h_timer_running(txtimer) && h_timer_expired(txtimer)) {
  814. #if H_DEBUG
  815. if (loglevel==0)
  816.    message(0," <- TxTimer (timer=%08lx  time=%08lx)",
  817.            txtimer,time(NULL));
  818. #endif
  819.            return (H_TXTIME);
  820.         }
  821.         if (h_timer_running(devtxtimer) && h_timer_expired(devtxtimer)) {
  822. #if H_DEBUG
  823. if (loglevel==0)
  824.    message(0," <- DevTxTimer (timer=%08lx  time=%08lx)",
  825.            devtxtimer,time(NULL));
  826. #endif
  827.            return (H_DEVTXTIME);
  828.         }
  829.  
  830.         sys_idle();
  831.         return (H_NOPKT);
  832. }/*rxpkt()*/
  833.  
  834.  
  835. /*---------------------------------------------------------------------------*/
  836. static void hydra_status (boolean xmit)
  837. {
  838.         long pos    = xmit ? txpos    : rxpos,
  839.              fsize  = xmit ? txfsize  : rxfsize;
  840.  
  841.         hydra_gotoxy(46,xmit ? 1 : 2);
  842.         if (pos >= fsize)
  843.            hydra_printf("%ld/%ld (EOF)",pos,fsize);
  844.         else {
  845.            int left = (int) ((((fsize - pos) / 128L) * 1340L) / cur_speed);
  846.            char *p = "";
  847.  
  848.            if (xmit) {
  849.               if      (txstate == HTX_DATAACK) p = "ACK ";
  850.               else if (txstate == HTX_XWAIT)   p = "WAIT ";
  851.            }
  852.            hydra_printf("%ld/%ld (%s%d:%02d min left)",
  853.                         pos, fsize, p, left / 60, left % 60);
  854.         }
  855.         hydra_clreol();
  856. }/*hydra_status()*/
  857.  
  858.  
  859. /*---------------------------------------------------------------------------*/
  860. static void hydra_pct (boolean xmit)
  861. {
  862.         long offset = xmit ? txoffset : rxoffset,
  863.              fsize  = xmit ? txfsize  : rxfsize,
  864.              start  = xmit ? txstart  : rxstart,
  865.              elapsed, bytes, cps, pct;
  866.  
  867.         elapsed = time(NULL) - start;
  868.         bytes = fsize - offset;
  869.         if (bytes < 1024L || elapsed == 0L)
  870.            return;
  871.         cps = bytes / elapsed;
  872.         pct = (cps * 1000L) / ((long) cur_speed);
  873.         message(2,"+%s-H CPS: %ld (%ld bytes), %d:%02d min.  Eff: %ld%%",
  874.                 xmit ? "Sent" : "Rcvd", cps, bytes,
  875.                 (int) (elapsed / 60), (int) (elapsed % 60), pct);
  876. }/*hydra_pct()*/
  877.  
  878.  
  879. /*---------------------------------------------------------------------------*/
  880. void hydra_badxfer (void)
  881. {
  882.         if (rxfd >= 0) {
  883.            dos_close(rxfd);
  884.            rxfd = -1;
  885.            if (xfer_bad())
  886.               message(1,"+HRECV: Bad xfer recovery-info saved");
  887.            else
  888.               message(0,"-HRECV: Bad xfer - file deleted");
  889.         }
  890. }/*hydra_badxfer()*/
  891.  
  892.  
  893. /*---------------------------------------------------------------------------*/
  894. void hydra_init (dword want_options)
  895. {
  896.         register word i, j;
  897.         word  crc16;
  898.         dword crc32;
  899.  
  900.         txbuf    = (byte *)  malloc(H_BUFLEN);
  901.         rxbuf    = (byte *)  malloc(H_BUFLEN);
  902.         crc16tab = (word *)  malloc(256 * ((int) sizeof (word)));
  903.         crc32tab = (dword *) malloc(256 * ((int) sizeof (dword)));
  904.         if (!txbuf || !rxbuf || !crc16tab || !crc32tab) {
  905.            message(6,"!HYDRA: Can't allocate buffers!");
  906.            endprog(2);
  907.         }
  908.         txbufin  = txbuf + ((H_MAXBLKLEN + H_OVERHEAD + 5) * 2);
  909.         rxbufmax = rxbuf + H_MAXPKTLEN;
  910.  
  911.         for (i = 0; i < 256; i++) {
  912.             crc16 = i;
  913.             crc32 = i;
  914.             for (j = 8; j > 0; j--) {
  915.                 if (crc16 & 1) crc16 = (crc16 >> 1) ^ h_crc16poly;
  916.                 else           crc16 >>= 1;
  917.                 if (crc32 & 1) crc32 = (crc32 >> 1) ^ h_crc32poly;
  918.                 else           crc32 >>= 1;
  919.             }
  920.             crc16tab[i] = crc16;
  921.             crc32tab[i] = crc32;
  922.         }
  923.  
  924.         batchesdone = 0;
  925.  
  926.         originator = nooriginator ? false : true;
  927.  
  928.         if (originator)
  929.            hdxlink = false;
  930.         else if (hdxsession)
  931.            hdxlink = true;
  932.  
  933.         options = (want_options & HCAN_OPTIONS) & ~HUNN_OPTIONS;
  934.  
  935.         timeout = (word) (40960L / cur_speed);
  936.         if      (timeout < H_MINTIMER) timeout = H_MINTIMER;
  937.         else if (timeout > H_MAXTIMER) timeout = H_MAXTIMER;
  938.  
  939.         txmaxblklen = (cur_speed / 300) * 128;
  940.         if      (txmaxblklen < 256)         txmaxblklen = 256;
  941.         else if (txmaxblklen > H_MAXBLKLEN) txmaxblklen = H_MAXBLKLEN;
  942.  
  943.         rxblklen = txblklen = (cur_speed < 2400U) ? 256 : 512;
  944.  
  945.         txgoodbytes  = 0;
  946.         txgoodneeded = 1024;
  947.  
  948.         txstate = HTX_DONE;
  949.  
  950.         if (!mailer)
  951.            message(-1,"+HYDRA session (%s-directional mode)",
  952.                       hdxlink ? "Uni" : "Bi");
  953.  
  954. #if WIN_AGL
  955. { byte ev   = win_maxver - 25,          /* extra lines available vertically? */
  956.        elog = ev / 3,                   /* 1/3 of extra lines for log_win    */
  957.        eloc = ev / 3,                   /* 1/3 of extra lines for local_win  */
  958.        erem = ev - (elog + eloc);       /* the rest is extra for remote_win  */
  959.  
  960.         log_win = win_create(1, 1, win_maxhor, 6 + elog,
  961.                               CUR_NONE, CON_RAW | CON_WRAP | CON_SCROLL,
  962.                               CHR_NORMAL, KEY_RAW);
  963.         win_setattrib(log_win,CHR_INVERSE);
  964.         win_clreol(log_win);
  965.         win_printf(log_win," %s v%s - COPYRIGHT (C) 1991-1993 A.G.Lentz, LENTZ SOFTWARE-DEVELOPMENT",PRGNAME,VERSION);
  966.         win_setattrib(log_win,CHR_NORMAL);
  967.         win_setrange(log_win,1,2,win_maxhor,6 + elog);
  968.  
  969.         file_win = win_create(1, 7 + elog, win_maxhor, 9 + elog,
  970.                               CUR_NONE, CON_RAW, CHR_NORMAL, KEY_RAW);
  971.         win_setattrib(file_win,CHR_INVERSE);
  972.         win_clreol(file_win);
  973.         win_printf(file_win," Port=%u   ComSpeed=%u   LineSpeed=%u",
  974.                             port + 1, com_speed, cur_speed);
  975.         win_xyputs(file_win,48,1,"Press ESC to abort Hydra session");
  976.         win_setattrib(file_win,CHR_F_YELLOW);
  977.         win_xyputs(file_win,2,2,"Sending  :");
  978.         win_xyputs(file_win,2,3,"Receiving:");
  979.         win_setattrib(file_win,CHR_NORMAL);
  980.         win_setrange(file_win,1,2,win_maxhor,3);
  981.  
  982.         remote_win = win_create(1, 10 + elog, win_maxhor, 17 + elog + erem,
  983.                                 CUR_NONE, CON_COOKED | CON_WRAP | CON_SCROLL,
  984.                                 CHR_NORMAL, KEY_RAW);
  985.         win_setattrib(remote_win,CHR_INVERSE);
  986.         win_fill(remote_win,177);
  987.         win_puts(remote_win," Remote ");
  988.         win_setattrib(remote_win,CHR_NORMAL);
  989.         win_setrange(remote_win,1,2,win_maxhor,8 + erem);
  990.         win_cls(remote_win);
  991.  
  992.         local_win = win_create(1, 18 + elog + erem, win_maxhor, win_maxver,
  993.                                CUR_NORMAL, CON_COOKED | CON_WRAP | CON_SCROLL,
  994.                                CHR_NORMAL, KEY_RAW);
  995.         win_setattrib(local_win,CHR_INVERSE);
  996.         win_fill(local_win,177);
  997.         win_puts(local_win," Local (Press Alt-C to start/end chat mode) ");
  998.         win_setattrib(local_win,CHR_NORMAL);
  999.         win_setrange(local_win,1,2,win_maxhor,8 + eloc);
  1000.         win_cls(local_win);
  1001.  
  1002.         log_first = false;
  1003.  
  1004.         win_settop(log_win);
  1005.         win_settop(file_win);
  1006.         win_settop(remote_win);
  1007.         win_settop(local_win);
  1008. }
  1009. #elif defined(AMIGA)
  1010.     ConPrintf(LogRequest,"\33[7m %s v%s - COPYRIGHT (C) 1991-1993 A.G.Lentz, LENTZ SOFTWARE-DEVELOPMENT\33[27m\n",PRGNAME,VERSION);
  1011.     ConPrintf(FileRequest,"\33[1;48HPress ESC to abort Hydra session\n");
  1012.     ConPrintf(FileRequest,"\33[2;2HSending  :\33[3;2HReceiving:");
  1013. #else
  1014. { struct text_info ti;
  1015.  
  1016.         term_x = wherex();
  1017.         term_y = wherey();
  1018.         gettextinfo(&ti);
  1019.         window(1,1,ti.screenwidth,ti.screenheight);
  1020.         term_scr = malloc(ti.screenwidth * ti.screenheight * sizeof (word));
  1021.         gettext(1,1,ti.screenwidth,ti.screenheight,term_scr);
  1022.  
  1023.         clrscr();
  1024.         textbackground(LIGHTGRAY);
  1025.         textcolor(BLACK);
  1026.  
  1027.         gotoxy(1,1);
  1028.         clreol();
  1029.         cprintf(" %s v%s - COPYRIGHT (C) 1991-1993 A.G.Lentz, LENTZ SOFTWARE-DEVELOPMENT",PRGNAME,VERSION);
  1030.  
  1031.         gotoxy(1,7);
  1032.         clreol();
  1033.         cprintf(" Port=%u   ComSpeed=%u   LineSpeed=%u",
  1034.                 port + 1, com_speed, cur_speed);
  1035.         gotoxy(48,7);
  1036.         cprintf("Press ESC to abort Hydra session");
  1037.  
  1038.         gotoxy(1,10);
  1039.         for (i = 0; i < ti.screenwidth; i++) putch(177);
  1040.         gotoxy(1,10);
  1041.         cprintf(" Remote ");
  1042.  
  1043.         gotoxy(1,18);
  1044.         for (i = 0; i < ti.screenwidth; i++) putch(177);
  1045.         gotoxy(1,18);
  1046.         cprintf(" Local (Press Alt-C to start/end chat mode) ");
  1047.  
  1048.         textbackground(BLACK);
  1049.         textcolor(YELLOW);
  1050.         gotoxy(2,8);
  1051.         cprintf("Sending  :");
  1052.         gotoxy(2,9);
  1053.         cprintf("Receiving:");
  1054.  
  1055.         window(1,19,80,25);
  1056.         textcolor(LIGHTGRAY);
  1057.         file_x = file_y = remote_x = remote_y = local_x = local_y = 1;
  1058.         log_y = 0;
  1059. }
  1060. #endif
  1061.  
  1062.         hydra_devfunc("CON",rem_chat);
  1063.  
  1064.         chatfill  = 0;
  1065.         chattimer = -1L;
  1066.         lasttimer = 0L;
  1067.  
  1068.         message(2,"+HYDRA session (%s-directional mode)",
  1069.                   hdxlink ? "Uni" : "Bi");
  1070. }/*hydra_init()*/
  1071.  
  1072.  
  1073. /*---------------------------------------------------------------------------*/
  1074. void hydra_deinit (void)
  1075. {
  1076. #if WIN_AGL
  1077.         win_settop(0);
  1078.         win_close(file_win);
  1079.         win_close(log_win);
  1080.         win_close(remote_win);
  1081.         win_close(local_win);
  1082.         file_win = 0;
  1083. #elif defined(AMIGA)
  1084. /* */
  1085. #else
  1086. { struct text_info ti;
  1087.  
  1088.         gettextinfo(&ti);
  1089.         window(1,1,ti.screenwidth,ti.screenheight);
  1090.         puttext(1,1,ti.screenwidth,ti.screenheight,term_scr);
  1091.         gotoxy(term_x,term_y);
  1092.         free(term_scr);
  1093.         file_x = 0;
  1094. }
  1095. #endif
  1096.  
  1097.         free(txbuf);
  1098.         free(rxbuf);
  1099.         free(crc16tab);
  1100.         free(crc32tab);
  1101. }/*hydra_deinit()*/
  1102.  
  1103.  
  1104. /*---------------------------------------------------------------------------*/
  1105. int hydra (char *txpathname, char *txalias)
  1106. {
  1107.         int   res;
  1108.         int   pkttype;
  1109.         char *p, *q;
  1110.         int   i;
  1111.         struct stat f;
  1112.  
  1113.         /*-------------------------------------------------------------------*/
  1114.         if (txstate == HTX_DONE) {
  1115.            txstate        = HTX_START;
  1116.            hydra_gotoxy(13,1);
  1117.            hydra_printf("Init");
  1118.            txoptions      = HTXI_OPTIONS;
  1119.            txpktprefix[0] = '\0';
  1120.  
  1121.            rxstate   = HRX_INIT;
  1122.            hydra_gotoxy(13,2);
  1123.            hydra_printf("Init");
  1124.            rxoptions = HRXI_OPTIONS;
  1125.            rxfd      = -1;
  1126.            rxdle     = 0;
  1127.            rxbufptr  = NULL;
  1128.            rxtimer   = h_timer_reset();
  1129.  
  1130.            devtxid    = devrxid = 0L;
  1131.            devtxtimer = h_timer_reset();
  1132.            devtxstate = HTD_DONE;
  1133.  
  1134.            braindead = h_timer_set(H_BRAINDEAD);
  1135.         }
  1136.         else
  1137.            txstate = HTX_FINFO;
  1138.  
  1139.         txtimer   = h_timer_reset();
  1140.         txretries = 0;
  1141.  
  1142.         /*-------------------------------------------------------------------*/
  1143.         if (txpathname) {
  1144.            stat(txpathname,&f);
  1145.            txfsize = f.st_size;
  1146.            txftime = f.st_mtime;
  1147.  
  1148.            if ((txfd = dos_sopen(txpathname,0)) < 0) {
  1149.               message(3,"-HSEND: Unable to open %s",txpathname);
  1150.               return (XFER_SKIP);
  1151.            }
  1152.  
  1153. #ifdef AMIGA
  1154.            strcpy(txfname,FilePart(txpathname));
  1155. #else
  1156.            strupr(txpathname);
  1157.            for (p=txpathname, q=txfname; *p; p++) {
  1158.                if (*q=*p, *p=='\\' || *p==':' || *p=='/')
  1159.                   q=txfname;
  1160.                else q++;
  1161.            }
  1162.            *q = '\0';
  1163.  
  1164.            if (txalias)
  1165.               strupr(txalias);
  1166. #endif    /* AMIGA */
  1167.  
  1168.            txstart  = 0L;
  1169.            txsyncid = 0L;
  1170.         }
  1171.         else {
  1172.            txfd = -1;
  1173.            strcpy(txfname,"");
  1174.         }
  1175.  
  1176.         /*-------------------------------------------------------------------*/
  1177.         do {
  1178.            /*----------------------------------------------------------------*/
  1179.            switch (devtxstate) {
  1180.                   /*---------------------------------------------------------*/
  1181.                   case HTD_DATA:
  1182.                        if (txstate > HTX_RINIT) {
  1183.                           h_long1(txbufin) = intell(devtxid);
  1184.                           p = ((char *) txbufin) + ((int) sizeof(long));
  1185.                           strcpy(p,devtxdev);
  1186.                           p += H_FLAGLEN + 1;
  1187.                           memcpy(p,devtxbuf,devtxlen);
  1188.                           txpkt(((int) sizeof (long)) + H_FLAGLEN + 1 + devtxlen,HPKT_DEVDATA);
  1189.                           devtxtimer = h_timer_set(timeout);
  1190.                           devtxstate = HTD_DACK;
  1191.                        }
  1192.                        break;
  1193.  
  1194.                   /*---------------------------------------------------------*/
  1195.                   default:
  1196.                        break;
  1197.  
  1198.                   /*---------------------------------------------------------*/
  1199.            }
  1200.  
  1201.            /*----------------------------------------------------------------*/
  1202.            switch (txstate) {
  1203.                   /*---------------------------------------------------------*/
  1204.                   case HTX_START:
  1205.                        com_putblock((byte *) autostr,(int) strlen(autostr));
  1206.                        txpkt(0,HPKT_START);
  1207.                        txtimer = h_timer_set(H_START);
  1208.                        txstate = HTX_SWAIT;
  1209.                        break;
  1210.  
  1211.                   /*---------------------------------------------------------*/
  1212.                   case HTX_INIT:
  1213.                        p = (char *) txbufin;
  1214.                        sprintf(p,"%08lx%s,%s %s",
  1215.                                  H_REVSTAMP,PRGNAME,VERSION,HC_OS);
  1216.                        p += ((int) strlen(p)) + 1;/* our app info & HYDRA rev. */
  1217.                        put_flags(p,h_flags,HCAN_OPTIONS);    /* what we CAN  */
  1218.                        p += ((int) strlen(p)) + 1;
  1219.                        put_flags(p,h_flags,options);         /* what we WANT */
  1220.                        p += ((int) strlen(p)) + 1;
  1221.                        sprintf(p,"%08lx%08lx",               /* TxRx windows */
  1222.                                  hydra_txwindow,hydra_rxwindow);
  1223.                        p += ((int) strlen(p)) + 1;
  1224.                        strcpy(p,pktprefix);     /* pkt prefix string we want */
  1225.                        p += ((int) strlen(p)) + 1;
  1226.  
  1227.                        txoptions = HTXI_OPTIONS;
  1228.                        txpkt((word) (((byte *) p) - txbufin), HPKT_INIT);
  1229.                        txoptions = rxoptions;
  1230.                        txtimer = h_timer_set(timeout / 2);
  1231.                        txstate = HTX_INITACK;
  1232.                        break;
  1233.  
  1234.                   /*---------------------------------------------------------*/
  1235.                   case HTX_FINFO:
  1236.                        if (txfd >= 0) {
  1237.                           if (!txretries) {
  1238.                              hydra_gotoxy(13,1);
  1239.                              hydra_printf(txfname);
  1240.                              if (txalias) {
  1241.                                 hydra_gotoxy(25,1);
  1242.                                 hydra_printf("  ->  %s",txalias);
  1243.                              }
  1244.                              hydra_clreol();
  1245.                              message(2,"+HSEND: %s%s%s (%ldb), %d min.",
  1246.                                      txpathname, txalias ? " -> " : "", txalias ? txalias : "",
  1247.                                      txfsize, (int) (txfsize * 10L / cur_speed + 27L) / 54L);
  1248.  
  1249.                              strlwr(txfname);
  1250.                           }
  1251.                           sprintf((char *) txbufin,"%08lx%08lx%08lx%08lx%08lx%s",
  1252.                                   txftime, txfsize, 0L, 0L, 0L,
  1253.                                   txalias ? txalias : txfname);
  1254.                        }
  1255.                        else {
  1256.                           if (!txretries) {
  1257.                              hydra_gotoxy(13,1);
  1258.                              hydra_printf("End of batch");
  1259.                              hydra_clreol();
  1260.                              message(1,"+HSEND: End of batch");
  1261.                           }
  1262.                           strcpy((char *) txbufin,txfname);
  1263.                        }
  1264.                        txpkt(((int) strlen((char *) txbufin)) + 1,HPKT_FINFO);
  1265.                        txtimer = h_timer_set(txretries ? timeout / 2 : timeout);
  1266.                        txstate = HTX_FINFOACK;
  1267.                        break;
  1268.  
  1269.                   /*---------------------------------------------------------*/
  1270.                   case HTX_XDATA:
  1271.                        if (com_outfull() > txmaxblklen)
  1272.                           break;
  1273.  
  1274.                        if (txpos < 0L)
  1275.                           i = -1;                                    /* Skip */
  1276.                        else {
  1277.                           h_long1(txbufin) = intell(txpos);
  1278.                           if ((i = dos_read(txfd,txbufin + ((int) sizeof (long)),txblklen)) < 0) {
  1279.                              message(6,"!HSEND: File read error");
  1280.                              dos_close(txfd);
  1281.                              txfd = -1;
  1282.                              txpos = -2L;                            /* Skip */
  1283.                           }
  1284.                        }
  1285.  
  1286.                        if (i > 0) {
  1287.                           txpos += i;
  1288.                           txpkt(((int) sizeof (long)) + i, HPKT_DATA);
  1289.  
  1290.                           if (txblklen < txmaxblklen &&
  1291.                               (txgoodbytes += i) >= txgoodneeded) {
  1292.                              txblklen <<= 1;
  1293.                              if (txblklen >= txmaxblklen) {
  1294.                                 txblklen = txmaxblklen;
  1295.                                 txgoodneeded = 0;
  1296.                              }
  1297.                              txgoodbytes = 0;
  1298.                           }
  1299.  
  1300.                           if (txwindow && (txpos >= (txlastack + txwindow))) {
  1301.                              txtimer = h_timer_set(txretries ? timeout / 2 : timeout);
  1302.                              txstate = HTX_DATAACK;
  1303.                           }
  1304.  
  1305.                           if (!txstart)
  1306.                              txstart = time(NULL);
  1307.                           hydra_status(true);
  1308.                           break;
  1309.                        }
  1310.  
  1311.                        /* fallthrough to HTX_EOF */
  1312.  
  1313.                   /*---------------------------------------------------------*/
  1314.                   case HTX_EOF:
  1315.                        h_long1(txbufin) = intell(txpos);
  1316.                        txpkt((int) sizeof (long),HPKT_EOF);
  1317.                        txtimer = h_timer_set(txretries ? timeout / 2 : timeout);
  1318.                        txstate = HTX_EOFACK;
  1319.                        break;
  1320.  
  1321.                   /*---------------------------------------------------------*/
  1322.                   case HTX_END:
  1323.                        txpkt(0,HPKT_END);
  1324.                        txpkt(0,HPKT_END);
  1325.                        txtimer = h_timer_set(timeout / 2);
  1326.                        txstate = HTX_ENDACK;
  1327.                        break;
  1328.  
  1329.                   /*---------------------------------------------------------*/
  1330.                   default:
  1331.                        break;
  1332.  
  1333.                   /*---------------------------------------------------------*/
  1334.            }
  1335.  
  1336.            /*----------------------------------------------------------------*/
  1337.            while (txstate && (pkttype = rxpkt()) != H_NOPKT) {
  1338.                  /*----------------------------------------------------------*/
  1339.                  switch (pkttype) {
  1340.                         /*---------------------------------------------------*/
  1341.                         case H_CARRIER:
  1342.                         case H_CANCEL:
  1343.                         case H_SYSABORT:
  1344.                         case H_BRAINTIME:
  1345.                              switch (pkttype) {
  1346.                                     case H_CARRIER:   p = "Carrier lost";          break;
  1347.                                     case H_CANCEL:    p = "Aborted by other side"; break;
  1348.                                     case H_SYSABORT:  p = "Aborted by operator";   break;
  1349.                                     case H_BRAINTIME: p = "Other end died";        break;
  1350.                              }
  1351.                              message(3,"-HYDRA: %s",p);
  1352.                              txstate = HTX_DONE;
  1353.                              res = XFER_ABORT;
  1354.                              break;
  1355.  
  1356.                         /*---------------------------------------------------*/
  1357.                         case H_TXTIME:
  1358.                              if (txstate == HTX_XWAIT || txstate == HTX_REND) {
  1359.                                 txpkt(0,HPKT_IDLE);
  1360.                                 txtimer = h_timer_set(H_IDLE);
  1361.                                 break;
  1362.                              }
  1363.  
  1364.                              if (++txretries > H_RETRIES) {
  1365.                                 message(3,"-HSEND: Too many errors");
  1366.                                 txstate = HTX_DONE;
  1367.                                 res = XFER_ABORT;
  1368.                                 break;
  1369.                              }
  1370.  
  1371.                              message(0,"-HSEND: Timeout - Retry %u",txretries);
  1372.  
  1373.                              txtimer = h_timer_reset();
  1374.  
  1375.                              switch (txstate) {
  1376.                                     case HTX_SWAIT:    txstate = HTX_START; break;
  1377.                                     case HTX_INITACK:  txstate = HTX_INIT;  break;
  1378.                                     case HTX_FINFOACK: txstate = HTX_FINFO; break;
  1379.                                     case HTX_DATAACK:  txstate = HTX_XDATA; break;
  1380.                                     case HTX_EOFACK:   txstate = HTX_EOF;   break;
  1381.                                     case HTX_ENDACK:   txstate = HTX_END;   break;
  1382.                              }
  1383.                              break;
  1384.  
  1385.                         /*---------------------------------------------------*/
  1386.                         case H_DEVTXTIME:
  1387.                              if (++devtxretries > H_RETRIES) {
  1388.                                 message(3,"-HDEVTX: Too many errors");
  1389.                                 txstate = HTX_DONE;
  1390.                                 res = XFER_ABORT;
  1391.                                 break;
  1392.                              }
  1393.  
  1394.                              message(0,"-HDEVTX: Timeout - Retry %u",devtxretries);
  1395.  
  1396.                              devtxtimer = h_timer_reset();
  1397.                              devtxstate = HTD_DATA;
  1398.                              break;
  1399.  
  1400.                         /*---------------------------------------------------*/
  1401.                         case HPKT_START:
  1402.                              if (txstate == HTX_START || txstate == HTX_SWAIT) {
  1403.                                 txtimer = h_timer_reset();
  1404.                                 txretries = 0;
  1405.                                 txstate = HTX_INIT;
  1406.                                 braindead = h_timer_set(H_BRAINDEAD);
  1407.                              }
  1408.                              break;
  1409.  
  1410.                         /*---------------------------------------------------*/
  1411.                         case HPKT_INIT:
  1412.                              if (rxstate == HRX_INIT) {
  1413.                                 p = (char *) rxbuf;
  1414.                                 p += ((int) strlen(p)) + 1;
  1415.                                 q = p + ((int) strlen(p)) + 1;
  1416.                                 rxoptions  = options | HUNN_OPTIONS;
  1417.                                 rxoptions |= get_flags(q,h_flags);
  1418.                                 rxoptions &= get_flags(p,h_flags);
  1419.                                 rxoptions &= HCAN_OPTIONS;
  1420.                                 if (rxoptions < (options & HNEC_OPTIONS)) {
  1421.                                    message(6,"!HYDRA: Incompatible on this link");
  1422.                                    txstate = HTX_DONE;
  1423.                                    res = XFER_ABORT;
  1424.                                    break;
  1425.                                 }
  1426.                                 p = q + ((int) strlen(q)) + 1;
  1427.                                 rxwindow = txwindow = 0L;
  1428.                                 sscanf(p,"%08lx%08lx", &rxwindow,&txwindow);
  1429.                                 if (rxwindow < 0L) rxwindow = 0L;
  1430.                                 if (hydra_rxwindow &&
  1431.                                     (!rxwindow || hydra_rxwindow < rxwindow))
  1432.                                    rxwindow = hydra_rxwindow;
  1433.                                 if (txwindow < 0L) txwindow = 0L;
  1434.                                 if (hydra_txwindow &&
  1435.                                     (!txwindow || hydra_txwindow < txwindow))
  1436.                                    txwindow = hydra_txwindow;
  1437.                                 p += ((int) strlen(p)) + 1;
  1438.                                 strncpy(txpktprefix,p,H_PKTPREFIX);
  1439.                                 txpktprefix[H_PKTPREFIX] = '\0';
  1440.  
  1441.                                 if (!batchesdone) {
  1442.                                    long revstamp;
  1443.  
  1444.                                    p = (char *) rxbuf;
  1445.                                    sscanf(p,"%08lx",&revstamp);
  1446.                                    message(0,"*HYDRA: Other's HydraRev=%s",
  1447.                                            h_revdate(revstamp));
  1448.                                    p += 8;
  1449.                                    if ((q = strchr(p,',')) != NULL) *q = ' ';
  1450.                                    if ((q = strchr(p,',')) != NULL) *q = '/';
  1451.                                    message(0,"*HYDRA: Other's App.Info '%s'",p);
  1452.                                    put_flags((char *) rxbuf,h_flags,rxoptions);
  1453.                                    message(1,"*HYDRA: Using link options '%s'",rxbuf);
  1454.                                    if (txwindow || rxwindow)
  1455.                                       message(0,"*HYDRA: Window tx=%ld rx=%ld",
  1456.                                                 txwindow,rxwindow);
  1457.                                 }
  1458.  
  1459.                                 chattimer = (rxoptions & HOPT_DEVICE) ? 0L : -2L;
  1460.  
  1461.                                 txoptions = rxoptions;
  1462.                                 rxstate = HRX_FINFO;
  1463.                              }
  1464.  
  1465.                              txpkt(0,HPKT_INITACK);
  1466.                              break;
  1467.  
  1468.                         /*---------------------------------------------------*/
  1469.                         case HPKT_INITACK:
  1470.                              if (txstate == HTX_INIT || txstate == HTX_INITACK) {
  1471.                                 braindead = h_timer_set(H_BRAINDEAD);
  1472.                                 txtimer = h_timer_reset();
  1473.                                 txretries = 0;
  1474.                                 txstate = HTX_RINIT;
  1475.                              }
  1476.                              break;
  1477.  
  1478.                         /*---------------------------------------------------*/
  1479.                         case HPKT_FINFO:
  1480.                              if (rxstate == HRX_FINFO) {
  1481.                                 braindead = h_timer_set(H_BRAINDEAD);
  1482.                                 if (!rxbuf[0]) {
  1483.                                    hydra_gotoxy(13,2);
  1484.                                    hydra_printf("End of batch");
  1485.                                    hydra_clreol();
  1486.                                    message(1,"*HRECV: End of batch");
  1487.                                    rxpos = 0L;
  1488.                                    rxstate = HRX_DONE;
  1489.                                    batchesdone++;
  1490.                                 }
  1491.                                 else {
  1492.                                    long diskfree;
  1493.  
  1494.                                    rxfsize = rxftime = 0L;
  1495.                                    rxfname[0] = '\0';
  1496.                                    sscanf((char *) rxbuf,"%08lx%08lx%*08lx%*08lx%*08lx%s",
  1497.                                           &rxftime, &rxfsize, rxfname);
  1498. #ifndef AMIGA
  1499.                                    strupr(rxfname);
  1500. #endif    /* AMIGA */
  1501.                                    hydra_gotoxy(13,2);
  1502.                                    hydra_printf(rxfname);
  1503.                                    hydra_clreol();
  1504.  
  1505.                                    rxpathname = xfer_init(rxfname,rxfsize,rxftime);
  1506.  
  1507.                                    diskfree = freespace(rxpathname);
  1508.  
  1509.                                    if (!rxpathname) {   /* Already have file */
  1510.                                       if (single_done) {
  1511.                                          hydra_gotoxy(29,2);
  1512.                                          hydra_printf("Skipping additional files");
  1513.                                          message(1,"+HRECV: Skipping additional files (file %s)",rxfname);
  1514.                                          rxpos = -2L;
  1515.                                       }
  1516.                                       else {
  1517.                                          hydra_gotoxy(29,2);
  1518.                                          hydra_printf("Already have file");
  1519.                                          message(1,"+HRECV: Already have %s",rxfname);
  1520.                                          rxpos = -1L;
  1521.                                       }
  1522.                                    }
  1523.                                    else if (rxfsize + 10240L > diskfree) {
  1524.                                       hydra_gotoxy(29,2);
  1525.                                       hydra_printf("Not enough diskspace");
  1526.                                       message(6,"!HRECV: %s not enough diskspace: %ld > %ld",
  1527.                                               rxfname, rxfsize + 10240L, diskfree);
  1528.                                       rxpos = -2L;
  1529.                                    }
  1530.                                    else {
  1531.                                       if (fexist(rxpathname)) { /* Resuming? */
  1532.                                          if ((rxfd = dos_sopen(rxpathname,0)) < 0) {
  1533.                                             message(6,"!HRECV: Unable to re-open %s",rxpathname);
  1534.                                             rxpos = -2L;
  1535.                                          }
  1536.                                       }
  1537.                                       else if ((rxfd = dos_sopen(rxpathname,1)) < 0) {
  1538.                                          message(6,"!HRECV: Unable to create %s",rxpathname);
  1539.                                          rxpos = -2L;
  1540.                                       }
  1541.  
  1542.                                       if (rxfd >= 0) {
  1543.                                          message(2,"+HRECV: %s (%ldb), %d min.",
  1544.                                                  rxfname, rxfsize,
  1545.                                                  (int) (rxfsize * 10L / cur_speed + 27L) / 54L);
  1546.                                          if (dos_seek(rxfd,0L,SEEK_END) < 0L) {
  1547.                                             message(6,"!HRECV: File seek error");
  1548.                                             hydra_badxfer();
  1549.                                             rxpos = -2L;
  1550.                                          }
  1551.                                          else {
  1552.                                             rxoffset = rxpos = dos_tell(rxfd);
  1553.                                             if (rxpos < 0L) {
  1554.                                                message(6,"!HRECV: File tell error");
  1555.                                                hydra_badxfer();
  1556.                                                rxpos = -2L;
  1557.                                             }
  1558.                                             else {
  1559.                                                rxstart = 0L;
  1560.                                                rxtimer = h_timer_reset();
  1561.                                                rxretries = 0;
  1562.                                                rxlastsync = 0L;
  1563.                                                rxsyncid = 0L;
  1564.                                                hydra_status(false);
  1565.                                                if (rxpos > 0L) {
  1566.                                                   hydra_gotoxy(46,2);
  1567.                                                   hydra_printf("%ld/%ld",rxpos,rxfsize);
  1568.                                                   message(1,"+HRECV: Resuming from offset %ld (%d min. to go)",
  1569.                                                           rxpos, (int) ((rxfsize - rxoffset) * 10L / cur_speed + 27L) / 54L);
  1570.                                                }
  1571.                                                rxstate = HRX_DATA;
  1572.                                             }
  1573.                                          }
  1574.                                       }
  1575.                                    }
  1576.                                 }
  1577.                              }
  1578.                              else if (rxstate == HRX_DONE)
  1579.                                 rxpos = (!rxbuf[0]) ? 0L : -2L;
  1580.  
  1581.                              h_long1(txbufin) = intell(rxpos);
  1582.                              txpkt((int) sizeof (long),HPKT_FINFOACK);
  1583.                              break;
  1584.  
  1585.                         /*---------------------------------------------------*/
  1586.                         case HPKT_FINFOACK:
  1587.                              if (txstate == HTX_FINFO || txstate == HTX_FINFOACK) {
  1588.                                 braindead = h_timer_set(H_BRAINDEAD);
  1589.                                 txretries = 0;
  1590.                                 if (!txfname[0]) {
  1591.                                    txtimer = h_timer_set(H_IDLE);
  1592.                                    txstate = HTX_REND;
  1593.                                 }
  1594.                                 else {
  1595.                                    txtimer = h_timer_reset();
  1596.                                    txpos = intell(h_long1(rxbuf));
  1597.                                    if (txpos >= 0L) {
  1598.                                       txoffset = txpos;
  1599.                                       txlastack = txpos;
  1600.                                       hydra_status(true);
  1601.                                       if (txpos > 0L) {
  1602.                                          message(1,"+HSEND: Transmitting from offset %ld (%d min. to go)",
  1603.                                                  txpos, (int) ((txfsize - txoffset) * 10L / cur_speed + 27L) / 54L);
  1604.                                          if (dos_seek(txfd,txpos,SEEK_SET) < 0L) {
  1605.                                             message(6,"!HSEND: File seek error");
  1606.                                             dos_close(txfd);
  1607.                                             txfd = -1;
  1608.                                             txpos = -2L;
  1609.                                             txstate = HTX_EOF;
  1610.                                             break;
  1611.                                          }
  1612.                                       }
  1613.                                       txstate = HTX_XDATA;
  1614.                                    }
  1615.                                    else {
  1616.                                       dos_close(txfd);
  1617.                                       if (txpos == -1L) {
  1618.                                          hydra_gotoxy(29,1);
  1619.                                          hydra_printf("They already have file");
  1620.                                          message(1,"+HSEND: They already have %s",txfname);
  1621.                                          if (mailer)
  1622.                                             resultlog(true,txpathname,txfsize,0L);
  1623.                                          return (XFER_OK);
  1624.                                       }
  1625.                                       else {  /* (txpos < -1L) file NOT sent */
  1626.                                          hydra_gotoxy(29,1);
  1627.                                          hydra_printf("Skipping");
  1628.                                          message(1,"+HSEND: Skipping %s",txfname);
  1629.                                          return (XFER_SKIP);
  1630.                                       }
  1631.                                    }
  1632.                                 }
  1633.                              }
  1634.                              break;
  1635.  
  1636.                         /*---------------------------------------------------*/
  1637.                         case HPKT_DATA:
  1638.                              if (rxstate == HRX_DATA) {
  1639.                                 if (intell(h_long1(rxbuf)) != rxpos ||
  1640.                                     intell(h_long1(rxbuf)) < 0L) {
  1641.                                    if (intell(h_long1(rxbuf)) <= rxlastsync) {
  1642.                                       rxtimer = h_timer_reset();
  1643.                                       rxretries = 0;
  1644.                                    }
  1645.                                    rxlastsync = intell(h_long1(rxbuf));
  1646.  
  1647.                                    if (!h_timer_running(rxtimer) ||
  1648.                                        h_timer_expired(rxtimer)) {
  1649.                                       if (rxretries > 4) {
  1650.                                          if (txstate < HTX_REND &&
  1651.                                              !originator && !hdxlink) {
  1652.                                             hdxlink = true;
  1653.                                             rxretries = 0;
  1654.                                          }
  1655.                                       }
  1656.                                       if (++rxretries > H_RETRIES) {
  1657.                                          message(3,"-HRECV: Too many errors");
  1658.                                          txstate = HTX_DONE;
  1659.                                          res = XFER_ABORT;
  1660.                                          break;
  1661.                                       }
  1662.                                       if (rxretries == 1)
  1663.                                          rxsyncid++;
  1664.  
  1665.                                       rxblklen /= 2;
  1666.                                       i = rxblklen;
  1667.                                       if      (i <=  64) i =   64;
  1668.                                       else if (i <= 128) i =  128;
  1669.                                       else if (i <= 256) i =  256;
  1670.                                       else if (i <= 512) i =  512;
  1671.                                       else               i = 1024;
  1672.                                       message(0,"-HRECV: Bad pkt at %ld - Retry %u (newblklen=%u)",
  1673.                                               rxpos,rxretries,i);
  1674.                                       h_long1(txbufin) = intell(rxpos);
  1675.                                       h_long2(txbufin) = intell((long) i);
  1676.                                       h_long3(txbufin) = intell(rxsyncid);
  1677.                                       txpkt(3 * ((int) sizeof(long)),HPKT_RPOS);
  1678.                                       rxtimer = h_timer_set(timeout);
  1679.                                    }
  1680.                                 }
  1681.                                 else {
  1682.                                    braindead = h_timer_set(H_BRAINDEAD);
  1683.                                    rxpktlen -= (int) sizeof (long);
  1684.                                    rxblklen = rxpktlen;
  1685.                                    if (dos_write(rxfd,rxbuf + ((int) sizeof (long)),rxpktlen) < 0) {
  1686.                                       message(6,"!HRECV: File write error");
  1687.                                       hydra_badxfer();
  1688.                                       rxpos = -2L;
  1689.                                       rxretries = 1;
  1690.                                       rxsyncid++;
  1691.                                       h_long1(txbufin) = intell(rxpos);
  1692.                                       h_long2(txbufin) = intell(0L);
  1693.                                       h_long3(txbufin) = intell(rxsyncid);
  1694.                                       txpkt(3 * ((int) sizeof(long)),HPKT_RPOS);
  1695.                                       rxtimer = h_timer_set(timeout);
  1696.                                       break;
  1697.                                    }
  1698.                                    rxretries = 0;
  1699.                                    rxtimer = h_timer_reset();
  1700.                                    rxlastsync = rxpos;
  1701.                                    rxpos += rxpktlen;
  1702.                                    if (rxwindow) {
  1703.                                       h_long1(txbufin) = intell(rxpos);
  1704.                                       txpkt((int) sizeof(long),HPKT_DATAACK);
  1705.                                    }
  1706.                                    if (!rxstart)
  1707.                                       rxstart = time(NULL) -
  1708.                                                 ((rxpktlen * 10) / cur_speed);
  1709.                                    hydra_status(false);
  1710.                                 }/*badpkt*/
  1711.                              }/*rxstate==HRX_DATA*/
  1712.                              break;
  1713.  
  1714.                         /*---------------------------------------------------*/
  1715.                         case HPKT_DATAACK:
  1716.                              if (txstate == HTX_XDATA || txstate == HTX_DATAACK ||
  1717.                                  txstate == HTX_XWAIT ||
  1718.                                  txstate == HTX_EOF || txstate == HTX_EOFACK) {
  1719.                                 if (txwindow && intell(h_long1(rxbuf)) > txlastack) {
  1720.                                    txlastack = intell(h_long1(rxbuf));
  1721.                                    if (txstate == HTX_DATAACK &&
  1722.                                        (txpos < (txlastack + txwindow))) {
  1723.                                       txstate = HTX_XDATA;
  1724.                                       txretries = 0;
  1725.                                       txtimer = h_timer_reset();
  1726.                                    }
  1727.                                 }
  1728.                              }
  1729.                              break;
  1730.  
  1731.                         /*---------------------------------------------------*/
  1732.                         case HPKT_RPOS:
  1733.                              if (txstate == HTX_XDATA || txstate == HTX_DATAACK ||
  1734.                                  txstate == HTX_XWAIT ||
  1735.                                  txstate == HTX_EOF || txstate == HTX_EOFACK) {
  1736.                                 if (intell(h_long3(rxbuf)) != txsyncid) {
  1737.                                    txsyncid = intell(h_long3(rxbuf));
  1738.                                    txretries = 1;
  1739.                                    txtimer = h_timer_reset();
  1740.                                    txpos = intell(h_long1(rxbuf));
  1741.                                    if (txpos < 0L) {
  1742.                                       if (txfd >= 0) {
  1743.                                          hydra_gotoxy(29,1);
  1744.                                          hydra_printf("Skipping");
  1745.                                          message(1,"+HSEND: Skipping %s",txfname);
  1746.                                          dos_close(txfd);
  1747.                                          txfd = -1;
  1748.                                          txstate = HTX_EOF;
  1749.                                       }
  1750.                                       txpos = -2L;
  1751.                                       break;
  1752.                                    }
  1753.  
  1754.                                    if (txblklen > intell(h_long2(rxbuf)))
  1755.                                       txblklen = (word) intell(h_long2(rxbuf));
  1756.                                    else
  1757.                                       txblklen >>= 1;
  1758.                                    if      (txblklen <=  64) txblklen =   64;
  1759.                                    else if (txblklen <= 128) txblklen =  128;
  1760.                                    else if (txblklen <= 256) txblklen =  256;
  1761.                                    else if (txblklen <= 512) txblklen =  512;
  1762.                                    else                      txblklen = 1024;
  1763.                                    txgoodbytes = 0;
  1764.                                    txgoodneeded += 1024;
  1765.                                    if (txgoodneeded > 8192)
  1766.                                       txgoodneeded = 8192;
  1767.  
  1768.                                    hydra_status(true);
  1769.                                    message(0,"+HSEND: Resending from offset %ld (newblklen=%u)",
  1770.                                            txpos,txblklen);
  1771.                                    if (dos_seek(txfd,txpos,SEEK_SET) < 0L) {
  1772.                                       message(6,"!HSEND: File seek error");
  1773.                                       dos_close(txfd);
  1774.                                       txfd = -1;
  1775.                                       txpos = -2L;
  1776.                                       txstate = HTX_EOF;
  1777.                                       break;
  1778.                                    }
  1779.  
  1780.                                    if (txstate != HTX_XWAIT)
  1781.                                       txstate = HTX_XDATA;
  1782.                                 }
  1783.                                 else {
  1784.                                    if (++txretries > H_RETRIES) {
  1785.                                       message(3,"-HSEND: Too many errors");
  1786.                                       txstate = HTX_DONE;
  1787.                                       res = XFER_ABORT;
  1788.                                       break;
  1789.                                    }
  1790.                                 }
  1791.                              }
  1792.                              break;
  1793.  
  1794.                         /*---------------------------------------------------*/
  1795.                         case HPKT_EOF:
  1796.                              if (rxstate == HRX_DATA) {
  1797.                                 if (intell(h_long1(rxbuf)) < 0L) {
  1798.                                    hydra_badxfer();
  1799.                                    hydra_gotoxy(29,2);
  1800.                                    hydra_printf("Skipping");
  1801.                                    hydra_clreol();
  1802.                                    message(1,"+HRECV: Skipping %s",rxfname);
  1803.                                    rxstate = HRX_FINFO;
  1804.                                    braindead = h_timer_set(H_BRAINDEAD);
  1805.                                 }
  1806.                                 else if (intell(h_long1(rxbuf)) != rxpos) {
  1807.                                    if (intell(h_long1(rxbuf)) <= rxlastsync) {
  1808.                                       rxtimer = h_timer_reset();
  1809.                                       rxretries = 0;
  1810.                                    }
  1811.                                    rxlastsync = intell(h_long1(rxbuf));
  1812.  
  1813.                                    if (!h_timer_running(rxtimer) ||
  1814.                                        h_timer_expired(rxtimer)) {
  1815.                                       if (++rxretries > H_RETRIES) {
  1816.                                          message(3,"-HRECV: Too many errors");
  1817.                                          txstate = HTX_DONE;
  1818.                                          res = XFER_ABORT;
  1819.                                          break;
  1820.                                       }
  1821.                                       if (rxretries == 1)
  1822.                                          rxsyncid++;
  1823.  
  1824.                                       rxblklen /= 2;
  1825.                                       i = rxblklen;
  1826.                                       if      (i <=  64) i =   64;
  1827.                                       else if (i <= 128) i =  128;
  1828.                                       else if (i <= 256) i =  256;
  1829.                                       else if (i <= 512) i =  512;
  1830.                                       else               i = 1024;
  1831.                                       message(0,"-HRECV: Bad EOF at %ld - Retry %u (newblklen=%u)",
  1832.                                               rxpos,rxretries,i);
  1833.                                       h_long1(txbufin) = intell(rxpos);
  1834.                                       h_long2(txbufin) = intell((long) i);
  1835.                                       h_long3(txbufin) = intell(rxsyncid);
  1836.                                       txpkt(3 * ((int) sizeof(long)),HPKT_RPOS);
  1837.                                       rxtimer = h_timer_set(timeout);
  1838.                                    }
  1839.                                 }
  1840.                                 else {
  1841.                                    rxfsize = rxpos;
  1842.                                    dos_close(rxfd);
  1843.                                    rxfd = -1;
  1844.                                    hydra_pct(false);
  1845.  
  1846.                                    p = xfer_okay();
  1847.                                    if (p) {
  1848.                                       hydra_gotoxy(25,2);
  1849.                                       hydra_printf("  -> %s",p);
  1850.                                       message(1,"+HRECV: Dup file renamed: %s",p);
  1851.                                    }
  1852.  
  1853.                                    hydra_status(false);
  1854.                                    message(1,"+Rcvd-H %s",p ? p : rxfname);
  1855.                                    resultlog(false,p ? p : rxfname,rxfsize - rxoffset,time(NULL) - rxstart);
  1856.                                    rxstate = HRX_FINFO;
  1857.                                    braindead = h_timer_set(H_BRAINDEAD);
  1858.                                 }/*skip/badeof/eof*/
  1859.                              }/*rxstate==HRX_DATA*/
  1860.  
  1861.                              if (rxstate == HRX_FINFO)
  1862.                                 txpkt(0,HPKT_EOFACK);
  1863.                              break;
  1864.  
  1865.                         /*---------------------------------------------------*/
  1866.                         case HPKT_EOFACK:
  1867.                              if (txstate == HTX_EOF || txstate == HTX_EOFACK) {
  1868.                                 braindead = h_timer_set(H_BRAINDEAD);
  1869.                                 if (txfd >= 0) {
  1870.                                    txfsize = txpos;
  1871.                                    dos_close(txfd);
  1872.                                    hydra_pct(true);
  1873.                                    resultlog(true,txpathname,txfsize - txoffset,time(NULL) - txstart);
  1874.                                    return (XFER_OK);
  1875.                                 }
  1876.                                 else
  1877.                                    return (XFER_SKIP);
  1878.                              }
  1879.                              break;
  1880.  
  1881.                         /*---------------------------------------------------*/
  1882.                         case HPKT_IDLE:
  1883.                              if (txstate == HTX_XWAIT) {
  1884.                                 hdxlink = false;
  1885.                                 txtimer = h_timer_reset();
  1886.                                 txretries = 0;
  1887.                                 txstate = HTX_XDATA;
  1888.                              }
  1889.                              else if (txstate >= HTX_FINFO && txstate < HTX_REND)
  1890.                                 braindead = h_timer_set(H_BRAINDEAD);
  1891.                              break;
  1892.  
  1893.                         /*---------------------------------------------------*/
  1894.                         case HPKT_END:
  1895.                              /* special for chat, other side wants to quit */
  1896.                              if (chattimer > 0L && txstate == HTX_REND) {
  1897.                                 chattimer = -3L;
  1898.                                 break;
  1899.                              }
  1900.  
  1901.                              if (txstate == HTX_END || txstate == HTX_ENDACK) {
  1902.                                 txpkt(0,HPKT_END);
  1903.                                 txpkt(0,HPKT_END);
  1904.                                 txpkt(0,HPKT_END);
  1905.                                 message(1,"+HYDRA: Completed");
  1906.                                 txstate = HTX_DONE;
  1907.                                 res = XFER_OK;
  1908.                              }
  1909.                              break;
  1910.  
  1911.                         /*---------------------------------------------------*/
  1912.                         case HPKT_DEVDATA:
  1913.                              if (devrxid != intell(h_long1(rxbuf))) {
  1914.                                 hydra_devrecv();
  1915.                                 devrxid = intell(h_long1(rxbuf));
  1916.                              }
  1917.                              h_long1(txbufin) = intell(devrxid);
  1918.                              txpkt((int) sizeof (long),HPKT_DEVDACK);
  1919.                              break;
  1920.  
  1921.                         /*---------------------------------------------------*/
  1922.                         case HPKT_DEVDACK:
  1923.                              if (devtxstate && (devtxid == intell(h_long1(rxbuf)))) {
  1924.                                 devtxtimer = h_timer_reset();
  1925.                                 devtxstate = HTD_DONE;
  1926.                              }
  1927.                              break;
  1928.  
  1929.                         /*---------------------------------------------------*/
  1930.                         default:  /* unknown packet types: IGNORE, no error! */
  1931.                              break;
  1932.  
  1933.                         /*---------------------------------------------------*/
  1934.                  }/*switch(pkttype)*/
  1935.  
  1936.                  /*----------------------------------------------------------*/
  1937.                  switch (txstate) {
  1938.                         /*---------------------------------------------------*/
  1939.                         case HTX_START:
  1940.                         case HTX_SWAIT:
  1941.                              if (rxstate == HRX_FINFO) {
  1942.                                 txtimer = h_timer_reset();
  1943.                                 txretries = 0;
  1944.                                 txstate = HTX_INIT;
  1945.                              }
  1946.                              break;
  1947.  
  1948.                         /*---------------------------------------------------*/
  1949.                         case HTX_RINIT:
  1950.                              if (rxstate == HRX_FINFO) {
  1951.                                 txtimer = h_timer_reset();
  1952.                                 txretries = 0;
  1953.                                 txstate = HTX_FINFO;
  1954.                              }
  1955.                              break;
  1956.  
  1957.                         /*---------------------------------------------------*/
  1958.                         case HTX_XDATA:
  1959.                              if (rxstate && hdxlink) {
  1960.                                 message(3,"*HYDRA: %s",hdxmsg);
  1961.                                 hydra_devsend("MSG",(byte *) hdxmsg,(int) strlen(hdxmsg));
  1962.  
  1963.                                 txtimer = h_timer_set(H_IDLE);
  1964.                                 txstate = HTX_XWAIT;
  1965.                              }
  1966.                              break;
  1967.  
  1968.                         /*---------------------------------------------------*/
  1969.                         case HTX_XWAIT:
  1970.                              if (!rxstate) {
  1971.                                 txtimer = h_timer_reset();
  1972.                                 txretries = 0;
  1973.                                 txstate = HTX_XDATA;
  1974.                              }
  1975.                              break;
  1976.  
  1977.                         /*---------------------------------------------------*/
  1978.                         case HTX_REND:
  1979.                              if (!rxstate && !devtxstate) {
  1980.                                 /* special for chat, braindead will protect */
  1981.                                 if (chattimer > 0L) break;
  1982.                                 if (chattimer == 0L) chattimer = -3L;
  1983.  
  1984.                                 txtimer = h_timer_reset();
  1985.                                 txretries = 0;
  1986.                                 txstate = HTX_END;
  1987.                              }
  1988.                              break;
  1989.  
  1990.                         /*---------------------------------------------------*/
  1991.                  }/*switch(txstate)*/
  1992.            }/*while(txstate&&pkttype)*/
  1993.         } while (txstate);
  1994.  
  1995.         if (txfd >= 0)
  1996.            dos_close(txfd);
  1997.         hydra_badxfer();
  1998.  
  1999.         if (res == XFER_ABORT) {
  2000.            com_dump();
  2001.            if (carrier()) {
  2002.               com_putblock((byte *) abortstr,(int) strlen(abortstr));
  2003.               com_flush();
  2004.            }
  2005.            com_purge();
  2006.         }
  2007.         else
  2008.            com_flush();
  2009.  
  2010.         return (res);
  2011. }/*hydra()*/
  2012.  
  2013.  
  2014. /* end of hydra.c */
  2015.